package com.home.qh.webapp.controller;

import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.home.qh.model.AdditionalClause;
import com.home.qh.model.Bill;
import com.home.qh.model.Booking;
import com.home.qh.model.Customer;
import com.home.qh.model.GoodsStatus;
import com.home.qh.model.Nos;
import com.home.qh.model.Partner;
import com.home.qh.model.Paying;
import com.home.qh.model.Port;
import com.home.qh.model.Store;
import com.home.qh.model.TransCtrType;
import com.home.qh.model.TransFreight;
import com.home.qh.model.TransGoodsDesc;
import com.home.qh.model.TransParty;
import com.home.qh.model.Voyage;
import com.home.qh.service.AdditionalClauseManager;
import com.home.qh.service.BookingManager;
import com.home.qh.service.CityManager;
import com.home.qh.service.ClauseManager;
import com.home.qh.service.CommodityManager;
import com.home.qh.service.CtrKindPackageManager;
import com.home.qh.service.CustomerManager;
import com.home.qh.service.EquipmentManager;
import com.home.qh.service.FeeManager;
import com.home.qh.service.GoodsStatusManager;
import com.home.qh.service.KindPackageManager;
import com.home.qh.service.NosManager;
import com.home.qh.service.PartnerManager;
import com.home.qh.service.PayingManager;
import com.home.qh.service.PortManager;
import com.home.qh.service.StoreManager;
import com.home.qh.service.TransCtrTypeManager;
import com.home.qh.service.TransFreightManager;
import com.home.qh.service.TransGoodsDescManager;
import com.home.qh.service.TransPartyManager;
import com.home.qh.service.VoyageManager;

@Controller
@RequestMapping("/booking/edit_booking.*")
public class BookingFormController extends BaseFormController {
	private transient final Log log = LogFactory.getLog(BookingFormController.class);
	private PortManager portManager;
	private BookingManager bookingManager;
	private VoyageManager voyageManager;
	private CustomerManager customerManager;
	private PartnerManager partnerManager;
	private PayingManager payingManager;
	private NosManager nosManager;
	private GoodsStatusManager goodsStatusManager;
	private StoreManager storeManager;
	private TransCtrTypeManager transCtrTypeManager;
	private CityManager cityManager;
	private TransPartyManager transPartyManager;
	private ClauseManager clauseManager;
	private AdditionalClauseManager additionalClauseManager;
	private TransFreightManager transFreightManager;
	private FeeManager feeManager;
	private EquipmentManager equipmentManager;
	private CommodityManager commodityManager;
	private KindPackageManager kindPackageManager;
	private CtrKindPackageManager ctrKindPackageManager;
	private TransGoodsDescManager transGoodsDescManager;
	
	
	@Autowired
	private ApplicationContext context;
	
	@Autowired
	public void setPortManager(PortManager portManager) {
		this.portManager = portManager;
	}
	
	@Autowired
	public void setBookingManager(BookingManager bookingManager) {
		this.bookingManager = bookingManager;
	}
	
	@Autowired
	public void setVoyageManager(VoyageManager voyageManager) {
		this.voyageManager = voyageManager;
	}
	
	@Autowired
	public void setCustomerManager(CustomerManager customerManager) {
		this.customerManager = customerManager;
	}
	
	@Autowired
	public void setPartnerManager(PartnerManager partnerManager) {
		this.partnerManager = partnerManager;
	}	
	
	@Autowired
	public void setPayingManager(PayingManager payingManager) {
		this.payingManager = payingManager;
	}
	
	@Autowired
	public void setNosManager(NosManager nosManager) {
		this.nosManager = nosManager;
	}

	@Autowired
	public void setGoodStatusManager(GoodsStatusManager goodsStatusManager) {
		this.goodsStatusManager = goodsStatusManager;
	}
	
	@Autowired
	public void setStoreManager(StoreManager storeManager) {
		this.storeManager = storeManager;
	}
	
	@Autowired
	public void setTransCtrTypeManager(TransCtrTypeManager transCtrTypeManager) {
		this.transCtrTypeManager = transCtrTypeManager;
	}
	
	@Autowired
	public void setCityManager(CityManager cityManager) {
		this.cityManager = cityManager;
	}
	
	@Autowired
	public void setTransPartyManager(TransPartyManager transPartyManager) {
		this.transPartyManager = transPartyManager;
	}
	
	@Autowired
	public void setClauseManager(ClauseManager clauseManager) {
		this.clauseManager = clauseManager;
	}
	
	@Autowired
	public void setAdditionalClauseManager(AdditionalClauseManager additionalClauseManager) {
		this.additionalClauseManager = additionalClauseManager;
	}
	
	@Autowired
	public void setTransFreightManager(TransFreightManager transFreightManager) {
		this.transFreightManager = transFreightManager;
	}
	
	@Autowired
	public void setFeeManager(FeeManager feeManager) {
		this.feeManager = feeManager;
	}
	
	@Autowired
	public void setKindPackageManager(KindPackageManager kindPackageManager) {
		this.kindPackageManager = kindPackageManager;
	}
	
	@Autowired
	public void setCtrKindPackageManager(CtrKindPackageManager ctrKindPackageManager) {
		this.ctrKindPackageManager = ctrKindPackageManager;
	}
	
	@Autowired
	public void setEquipmentManager(EquipmentManager equipmentManager) {
		this.equipmentManager = equipmentManager;
	}
	
	@Autowired
	public void setCommodityManager(CommodityManager commodityManager) {
		this.commodityManager = commodityManager;
	}
	
	@Autowired
	public void setTransGoodsDescManager(TransGoodsDescManager transGoodsDescManager) {
		this.transGoodsDescManager = transGoodsDescManager;
	}
	
    public BookingFormController() {
        setCancelView("redirect:/booking/view_booking.html");
        setSuccessView("redirect:/booking/view_booking.html");
    }
    
    @Override
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) {
		super.initBinder(request, binder);
        binder.registerCustomEditor(Paying.class, "paying", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Paying paying = payingManager.get(longId);
        			setValue(paying);
        		}
        	}
        });
        
        binder.registerCustomEditor(Voyage.class, "voyage", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Voyage voyage = voyageManager.get(longId);
        			setValue(voyage);
        		}
        	}
        });
        
        binder.registerCustomEditor(Customer.class, "shipper", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Customer customer = customerManager.get(longId);
        			setValue(customer);
        		}
        	}
        });
        
        binder.registerCustomEditor(Customer.class, "consignee", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Customer customer = customerManager.get(longId);
        			setValue(customer);
        		}
        	}
        });
        
        binder.registerCustomEditor(Partner.class, "partner", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Partner partner = partnerManager.get(longId);
        			setValue(partner);
        		}
        	}
        });
        
        binder.registerCustomEditor(Nos.class, "nos", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Nos nos = nosManager.get(longId);
        			setValue(nos);
        		}
        	}
        });
        
        binder.registerCustomEditor(GoodsStatus.class, "goodStatus", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			GoodsStatus goodStatus = goodsStatusManager.get(longId);
        			setValue(goodStatus);
        		}
        	}
        });
        
        binder.registerCustomEditor(Store.class, "ctrStore", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Store store = storeManager.get(longId);
        			setValue(store);
        		}
        	}
        });
        
        binder.registerCustomEditor(Port.class, "portLoading", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Port portLoading = portManager.get(longId);
        			setValue(portLoading);
        		}
        	}
        });
        
        binder.registerCustomEditor(Port.class, "portDischarge", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			Port portDischarge = portManager.get(longId);
        			setValue(portDischarge);
        		}
        	}
        });
        
        binder.registerCustomEditor(TransCtrType.class, "transCtrType", new PropertyEditorSupport() {
        	public void setAsText(String id) {
        		long longId = Long.parseLong(id);
        		if (longId > 0) {
        			TransCtrType transCtrType = transCtrTypeManager.get(longId);
        			setValue(transCtrType);
        		}
        	}
        });
		
	}

	@ModelAttribute
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
    protected ModelAndView showForm(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        ModelAndView view = new ModelAndView("booking/edit_booking");
        view.addObject("customerListing", customerManager.getAll());
        view.addObject("voyageListing", voyageManager.getAll());
        view.addObject("portListing", portManager.getAll());
        view.addObject("cityListing", cityManager.getAll());
        view.addObject("partnerListing", partnerManager.getAll());
        view.addObject("payingListing", payingManager.getAll());
        view.addObject("clauseListing",clauseManager.getAll());
        view.addObject("feeListing", feeManager.getAll());
        view.addObject("equipmentListing", equipmentManager.getAll());
        view.addObject("commodityListing", commodityManager.getAll());
        view.addObject("kindPackageListing", kindPackageManager.getAll());
        view.addObject("ctrKindPackageListing", ctrKindPackageManager.getAll());
        
        log.debug("entering edit_booking form ...");
        if (!isFormSubmission(request)) {
            String bookingId = request.getParameter("id"); 
            Booking booking = null;
            List<TransParty> transParties = new ArrayList<TransParty>();
            List<AdditionalClause> additionalClauses= new ArrayList<AdditionalClause>();
            List<TransFreight> transFreights = new ArrayList<TransFreight>();
            List<TransGoodsDesc> goodDescs = new ArrayList<TransGoodsDesc>();
	        if (bookingId == null || isAdd(request)) {
	        	booking = new Booking();
	        	Calendar cal = Calendar.getInstance();
	        	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyMM");
	        	String dateStr= simpleDateFormat.format(cal.getTime());
	        	int bookingOrderNumber = bookingManager.getOrderNumber();
	        	Date date = new Date();
	        	System.out.println("-----"+simpleDateFormat.format(cal.getTime()));
	        } else if (!StringUtils.isBlank(bookingId)) {
	        	booking = bookingManager.get(Long.parseLong(bookingId));
	        	transParties = bookingManager.getTransPartyByBooking(Long.parseLong(bookingId));
	        	additionalClauses = bookingManager.getAdditionalClauseByBooking(Long.parseLong(bookingId));
	        	transFreights = bookingManager.getTransFreightByBooking(Long.parseLong(bookingId));
	        	goodDescs = bookingManager.getTransGoodsDescByBooking(Long.parseLong(bookingId));
	        }
	        view.addObject("booking", booking);
	        view.addObject("transParties", transParties);
	        view.addObject("numberTranspaties",transParties.size());
	        view.addObject("additionalClauses",additionalClauses);
	        view.addObject("transFreights",transFreights);
	        view.addObject("goodDescs",goodDescs);
	        view.addObject("number_ac",additionalClauses.size());
        }
        
    	return view;
    }
    
    @RequestMapping(method = RequestMethod.POST)
    public String onSubmit(Booking booking, BindingResult errors, HttpServletRequest request,
                           HttpServletResponse response)
            throws Exception {
    	
        if (request.getParameter("cancel") != null) {
            if (!StringUtils.equals(request.getParameter("from"), "list")) {
                return getCancelView();
            } else {
                return getSuccessView();
            }
        }
        
        if (request.getParameter("create_bill") != null){
        	System.out.println("------------------ALO MOTO--------------");
        	Bill bill = new Bill();
        	return getSuccessView();
        }

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy");
        log.debug("entering 'onSubmit' method in edit_booking controller...");

        Locale locale = request.getLocale();

        if (request.getParameter("delete") != null) {
        	bookingManager.remove(booking.getId());
            return getSuccessView();
        } else {
        	if (booking == null)
        		booking = new Booking();   
        	log.debug("Save booking ...");
        	String bookingDateStr = (String) request.getParameter("bookingDate");
        	String issueDateStr = (String) request.getParameter("issueDate");
        	
        	try {
				Date date = simpleDateFormat.parse(bookingDateStr);
				booking.setBookingDate(date);
			} catch (Exception e) {
				booking.setBookingDate(null);
			}
        	
        	try {
				Date date = simpleDateFormat.parse(issueDateStr);
				booking.setIssueDate(date);
			} catch (Exception e) {
				booking.setIssueDate(null);
			}
        			
    		bookingManager.save(booking);
    		int number_transparties = Integer.parseInt((String)request.getParameter("number_transpaties"));
        	int number_saved = 1;
        	
            // TransParties process
        	if(booking.getId()!=null){
	        	List<TransParty> transParties = bookingManager.getTransPartyByBooking(booking.getId());
	        	for (TransParty transParty : transParties) {
					transPartyManager.remove(transParty.getId());
				}
        	}
        	
        	for (int i = 1; i <= number_transparties; i++) {
				long customer_id = Long.parseLong((String)request.getParameter("transparty"+i));
				if(customer_id>0){
    				String confirmed = (String)request.getParameter("confirmed"+i);
    				boolean isConfirmed = true;
    				if (confirmed==null) {
    					isConfirmed = false;
    				}
    				if(customer_id>0){
    					TransParty transParty = new TransParty(number_saved, customerManager.get(customer_id), booking);
    					transParty.setConfirmed(isConfirmed);
    					transPartyManager.save(transParty);
    					number_saved++;
    				}
				}
			}
        	
        	//Additional Clause process
        	if (booking.getId() != null){
        		List<AdditionalClause> additionalClauses = (List<AdditionalClause>)bookingManager.getAdditionalClauseByBooking(booking.getId());
        		for (AdditionalClause additionalClause : additionalClauses) {
        			additionalClauseManager.remove(additionalClause.getId());
				}
        	}
        	
        	String additionalClauseStr = (String)request.getParameter("additional-clause");
        	String [] additionalClauseArr = additionalClauseStr.split(",");
        	if(additionalClauseArr.length>0){
	        	for (int i = 0; i < additionalClauseArr.length; i++) {
	        		if (!additionalClauseArr[i].equals("")){
	        			AdditionalClause additionalClause = new AdditionalClause(i+1, clauseManager.get(Long.parseLong(additionalClauseArr[i])), booking);
	        			additionalClauseManager.save(additionalClause);
	        		}
				}
        	}
        	
        	//TransFreights process
        	if(booking.getId()!=null){
        		List<TransFreight> transFreights = (List<TransFreight>) bookingManager.getTransFreightByBooking(booking.getId());
        		for (TransFreight transFreight : transFreights) {
					transFreightManager.remove(transFreight.getId());
				}
        	}
        	
        	int number_transfreights = Integer.parseInt((String)request.getParameter("number_transfreights"));
        	
        	
        	for (int i = 1; i <= number_transfreights; i++) {
				String feeIdStr = (String) request.getParameter("fee"+i);
				
				if(feeIdStr!=null && !feeIdStr.equals("") && Long.parseLong(feeIdStr)>0){
					String payed = (String)request.getParameter("payed"+i);
					String amount = (String) request.getParameter("amount"+i);
					String payedDate = (String) request.getParameter("payedDate"+i);
					String desc = (String) request.getParameter("description"+i);
					
    				boolean isPayed = true;
    				if (payed==null) {
    					isPayed = false;
    				}
					TransFreight transFreight = new TransFreight(feeManager.get(Long.parseLong(feeIdStr)), booking);
					transFreight.setPayed(isPayed);
					
					if(amount!=null && !amount.equals(""))
						transFreight.setAmount(Double.parseDouble(amount));
					else
						transFreight.setAmount(0d);
					
					if(payedDate!=null && !payedDate.equals("")){
						try {
							Date date = simpleDateFormat.parse(payedDate);
							transFreight.setPayedDate(date);
						} catch (Exception e) {
							transFreight.setPayedDate(null);
						}
					}
					
					if(desc!=null)
						transFreight.setDescription(desc);
					else
						transFreight.setDescription("");
					
					transFreightManager.save(transFreight);
				}
			}
        	
        	//TransGoodsDesc process
        	if(booking.getId()!=null){
        		List<TransGoodsDesc> transGoodsDescs = (List<TransGoodsDesc>) bookingManager.getTransGoodsDescByBooking(booking.getId());
        		for (TransGoodsDesc transGoodsDesc : transGoodsDescs) {
					transGoodsDescManager.remove(transGoodsDesc.getId());
				}
        	}
        	
        	int number_good_desc = Integer.parseInt((String)request.getParameter("number_good_desc"));
        	
        	for (int i = 1; i <= number_good_desc; i++) {
        		String equipmentIdStr = (String) request.getParameter("equipment"+i);
        		String quantityStr = (String) request.getParameter("quantity"+i);
        		if (equipmentIdStr!=null && !equipmentIdStr.equals("") && Long.parseLong(equipmentIdStr)>0 && quantityStr!=null ){
        			TransGoodsDesc transGoodsDesc = new TransGoodsDesc(equipmentManager.get(Long.parseLong(equipmentIdStr)), booking, null);
        			String commodityIdStr = (String) request.getParameter("commodity"+i);
        			String weight = (String) request.getParameter("weight"+i);
        			String measurement = (String) request.getParameter("measurement"+i);
        			String sealNo = (String) request.getParameter("sealNo"+i);
        			String description = (String) request.getParameter("descriptionDesc"+i);
        			System.out.println("......................."+description);
        			String kindPackageIdStr = (String) request.getParameter("kindPackage"+i);
        			String ctrKindPackageIdStr = (String) request.getParameter("ctrKindPackage"+i);
        			
        			if (commodityIdStr!=null && !commodityIdStr.equals("") && Long.parseLong(commodityIdStr)>0){
        				transGoodsDesc.setCommodity(commodityManager.get(Long.parseLong(commodityIdStr)));
        			}
        			
        			if (kindPackageIdStr!=null && !kindPackageIdStr.equals("") && Long.parseLong(kindPackageIdStr)>0){
        				transGoodsDesc.setKindPackage(kindPackageManager.get(Long.parseLong(kindPackageIdStr)));
        			}
        			
        			if (ctrKindPackageIdStr!=null && !ctrKindPackageIdStr.equals("") && Long.parseLong(ctrKindPackageIdStr)>0){
        				transGoodsDesc.setCtrKindPackage(ctrKindPackageManager.get(Long.parseLong(ctrKindPackageIdStr)));
        			}
        			
        			if (!quantityStr.equals("")){
        				transGoodsDesc.setQuantity(Integer.parseInt(quantityStr));
        			}else{
        				transGoodsDesc.setQuantity(0);
        			}
        			
        			if (weight!=null && !weight.equals("")){
        				transGoodsDesc.setWeight(Double.parseDouble(weight));
        			}else{
        				transGoodsDesc.setWeight(0d);
        			}
        			
        			if (measurement!=null && !measurement.equals("")){
        				transGoodsDesc.setMeasurement(Double.parseDouble(measurement));
        			}else{
        				transGoodsDesc.setMeasurement(0d);
        			}
        			
        			if (sealNo!=null){
        				transGoodsDesc.setSealNo(sealNo);
        			}else{
        				transGoodsDesc.setSealNo("");
        			}
        			
        			if (description!=null){
        				transGoodsDesc.setDescription(description);
        			}else{
        				transGoodsDesc.setDescription("");
        			}
        			
        			transGoodsDescManager.save(transGoodsDesc);
        			
        		}
        	}
        	
            return getSuccessView();        	
        }
    }

    private boolean isFormSubmission(HttpServletRequest request) {
        return request.getMethod().equalsIgnoreCase("post");
    }

    protected boolean isAdd(HttpServletRequest request) {
        String method = request.getParameter("method");
        return (method != null && method.equalsIgnoreCase("add"));
    }
    
    private String getBookingOrderStr(int order){
    	if (order<10)
    		return "00"+order;
    	else if (order<100)
    		return "0"+order;
    	else
    		return ""+order;
    }

}
